<?php
/*
 * 小程序微信支付
 */
class wxpay{
    protected $url;//支付接口
    protected $appid;//小程序ID
	protected $mch_id;//商户id
    protected $key;//密钥
	protected $openid;//用户id
	protected $notify_url;
    function __construct($option){
        $this->url=$option['url'];
        $this->appid=$option['appid'];
        $this->openid=$option['openid'];
        $this->mch_id=$option['mch_id'];
        $this->key=$option['mch_key'];
        $this->notify_url=$option['notify_url'];
    }
    //支付订单
    public function pay($order=array()){
        $params=array(
            'appid'=>$this->appid,//小程序ID
            'mch_id'=>$this->mch_id,//商户号
            'nonce_str'=>$this->createNoncestr(),//随机字符串
            'body'=>$order['title'],//商品描述
            'out_trade_no'=>$order['order_no'],//商户订单号
            'total_fee'=>$order['amount']*100,//总金额 单位 分
            'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],//终端IP\
            'time_start'=>date('YmdHis'),//交易开始时间
            'time_expire'=>date('YmdHis',$order['expire_time']),//交易结束日期
            'notify_url'=>$this->notify_url,//通知地址
            'openid'=>$this->openid,//用户id
            'trade_type'=>'JSAPI'//交易类型
        );
      
        $params['sign']=$this->getSign($params);//下单签名
        $xmlData=arrayToXml($params);
        $return=xmlToArray(postXmlSSLCurl($xmlData,$this->url,60));
        if($return&&$return['return_code']=='SUCCESS'&&$return['result_code']=='SUCCESS')  {
            $pay_params=array(
                'appId'=>$this->appid,
                'timeStamp'=>time().'',//时间戳
                'nonceStr'=>$this->createNoncestr(),//随机串
                'package'=>'prepay_id='.$return['prepay_id'],//数据包
                'signType'=>'MD5',//签名方式
            );
            $pay_params['paySign']=$this->getSign($pay_params);
            return array('status'=>1,'data'=>$pay_params);
        }
        else{
            return array('status'=>0,'info'=>$return['return_code'].':'.$return['return_msg']);
        }
    }

	//作用：产生随机字符串，不长于32位
	private function createNoncestr($length = 32 ){
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
		$str ="";
        for ( $i = 0; $i < $length; $i++ )  {  
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
		}  
		return $str;
    }
    //作用：生成签名
    private function getSign($Obj){
		foreach ($Obj as $k => $v){
			$Parameters[$k] = $v;
		}
		//签名步骤一：按字典序排序参数
		ksort($Parameters);
		$String = $this->formatBizQueryParaMap($Parameters, false);
		//签名步骤二：在string后加入KEY
		$String = $String."&key=".$this->key;
		//签名步骤三：MD5加密
		$String = md5($String);
		//签名步骤四：所有字符转为大写
		$result_ = strtoupper($String);
		return $result_;
	}
	///作用：格式化参数，签名过程需要使用
	private function formatBizQueryParaMap($paraMap, $urlencode){
		$buff = "";
		ksort($paraMap);
		foreach ($paraMap as $k => $v){
		    if($urlencode)
		    {
			   $v = urlencode($v);
			}
			$buff .= $k . "=" . $v . "&";
		}
		$reqPar;
		if (strlen($buff) > 0){
			$reqPar = substr($buff, 0, strlen($buff)-1);
		}
		return $reqPar;
    }
}

function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key=>$val)
        {
             if (is_numeric($val))
             {
                $xml.="<".$key.">".$val."</".$key.">"; 

             }
             else
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";  
        }
        $xml.="</xml>";
        return $xml; 
    }

function xmlToArray($xml)
    {       
        //将XML转为array        
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);      
        return $array_data;
    }

function postXmlSSLCurl($xml,$url,$second=30)
    {
        $ch = curl_init();
        //超时时间
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        //这里设置代理，如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        //设置header
        curl_setopt($ch,CURLOPT_HEADER,FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
        //post提交方式
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        }
        else { 
            $error = curl_errno($ch);
            echo "curl出错，错误码:$error"."<br>"; 
            curl_close($ch);
            return false;
        }
    }